package cn.lingyangwl.framework.lock.model;

import cn.lingyangwl.framework.lock.exception.LockException;
import cn.lingyangwl.framework.tool.core.exception.Assert;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RLock;

import java.util.concurrent.TimeUnit;

/**
 * @author shenguangyang
 */
@Slf4j
public class RedissonLock extends LockTemplate {
    private final RLock rLock;

    public RedissonLock(String lockKey, Redisson redisson) {
        super(lockKey);
        Assert.notNull(redisson, "redisson is null");
        this.rLock = redisson.getLock(lockKey);
    }

    @Override
    public void unlock() {
        if (rLock.isLocked() && rLock.isHeldByCurrentThread()) {
            rLock.unlock();
        }
    }

    @Override
    public boolean isLocked() {
        return rLock.isLocked() && rLock.isHeldByCurrentThread();
    }

    @Override
    public boolean tryLock(long waitTime, TimeUnit unit) {
        try {
            // leaseTime: 占用时间, 这里默认设置5s, 内部会通过看门狗续期的
            rLock.tryLock(waitTime, unit.convert(5, TimeUnit.SECONDS), unit);
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
        return true;
    }

    @Override
    public void lock() {
        try {
            rLock.lock(5, TimeUnit.SECONDS);
        } catch (Exception e) {
            log.error("get lock fail, err: {}", e.getMessage());
            throw new LockException("get lock fail");
        }
    }
}
